package buy

import (
	"adam2/internal/model"
	"adam2/internal/properties"
	"adam2/internal/util"
	"anubis-framework/pkg/io"
	"gorm.io/gorm"
)

// 优化买
type OptimizeBuy struct {
	db *gorm.DB
}

// 初始化
func (o *OptimizeBuy) Init(db *gorm.DB) {
	o.db = db
}

// 执行
func (o *OptimizeBuy) DoBuy(transactionDate string) {
	io.Infoln("优化买")

	// 查询optimize_account表的记录
	var optimizeAccountArray *model.QuantAccountArray
	o.db.Raw("select * from optimize_account").Scan(&optimizeAccountArray)

	if optimizeAccountArray != nil && len(*optimizeAccountArray) > 0 {
		for _, optimizeAccount := range *optimizeAccountArray {

			var holdStockNumber int = optimizeAccount.HoldStockNumber
			// 如果某个账号的持股数量已经到达最大持股数量，则跳过这个账号
			if holdStockNumber >= properties.QuantProperties_.MaxHoldStockNumber {
				io.Infoln("账号[%s]的持股数量已经到达[%d]只，不再买入股票", optimizeAccount.AccountName, holdStockNumber)
				continue
			}

			// 根据账号名称，查询可以买入的股票
			var quantStockTransactRecordArray *model.QuantStockTransactRecordArray
			o.db.Raw("select t.* from quant_stock_transact_record t "+
				"join stock_transaction_data_all stda on stda.code_=t.stock_code and stda.date_=to_date(?, 'yyyy-mm-dd') "+
				"where t.account_name=? and t.sell_date is null and t.sell_price is null and t.sell_amount is null "+
				"and t.stock_code not in(select ostr.stock_code from optimize_stock_transact_record ostr "+
				"where ostr.sell_date is null and ostr.sell_price is null and ostr.sell_amount is null) and "+
				"t.stock_code not in("+
				"select si_.code_ from stock_info si_ where si_.last_transaction_date=to_date(?,'yyyy-mm-dd')) "+
				"order by stda.total_market_value asc",
				transactionDate, optimizeAccount.AccountName, transactionDate).Scan(&quantStockTransactRecordArray)

			if quantStockTransactRecordArray != nil && len(*quantStockTransactRecordArray) > 0 {
				for _, quantStockTransactRecord := range *quantStockTransactRecordArray {

					// 查询股票记录
					var stockTransactionDataAll *model.StockTransactionDataAll
					o.db.Raw("select * from stock_transaction_data_all t where t.code_=? and t.date_=to_date(?,'yyyy-mm-dd')",
						quantStockTransactRecord.StockCode, transactionDate).Scan(&stockTransactionDataAll)
					if stockTransactionDataAll == nil {
						io.Infoln("股票[%s]在日期[%s]没有交易记录，可能是停牌，跳过这只股票", quantStockTransactRecord.StockCode, transactionDate)
						continue
					}
					//if stockTransactionDataAll.OpenPrice == stockTransactionDataAll.ClosePrice {
					//	io.Infoln("股票[%s]在日期[%s]的开盘价和收盘价一样，可能是一字涨停版，跳过这只股票", quantStockTransactRecord.StockCode, transactionDate)
					//	continue
					//}
					if stockTransactionDataAll.OpenPrice < properties.QuantProperties_.OpenPriceBottomLimit {
						io.Infoln("股票[%s]在日期[%s]的开盘价为[%s]，小于[%s]，跳过这只股票", quantStockTransactRecord.StockCode, transactionDate, stockTransactionDataAll.OpenPrice, properties.QuantProperties_.OpenPriceBottomLimit)
						continue
					}

					// 如果股票的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个账号
					if util.CalculateBuyStockFee(stockTransactionDataAll.Code, stockTransactionDataAll.OpenPrice, 100) > float64(optimizeAccount.CapitalAssets) {
						break
					}

					// 如果可以买，则向optimize_stock_transact_record表中插入数据。
					// 计算应该买入股票的数量

					// 应当买入的股票的数量
					var shouldBuyStockNumber int = -1
					if len(*quantStockTransactRecordArray) <= (properties.QuantProperties_.MaxHoldStockNumber - optimizeAccount.HoldStockNumber) {
						shouldBuyStockNumber = len(*quantStockTransactRecordArray)
					} else {
						shouldBuyStockNumber = properties.QuantProperties_.MaxHoldStockNumber - optimizeAccount.HoldStockNumber
					}

					// 判断是否需要继续买入
					if shouldBuyStockNumber == 0 {
						io.Infoln("账号[%s]持股数量已经是%d，不再需要买入股票", optimizeAccount.AccountName, properties.QuantProperties_.MaxHoldStockNumber)
						break
					}

					// 计算买多少股
					// 买入多少股
					var buyOrSellAmount int = 100

					for optimizeAccount.CapitalAssets/float64(properties.QuantProperties_.MaxHoldStockNumber-optimizeAccount.HoldStockNumber) >= util.CalculateBuyStockFee(quantStockTransactRecord.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) {
						if util.CalculateBuyStockFee(quantStockTransactRecord.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) >= optimizeAccount.CapitalAssets/float64(properties.QuantProperties_.MaxHoldStockNumber-optimizeAccount.HoldStockNumber) {
							break
						}
						buyOrSellAmount = buyOrSellAmount + 100
					}
					if optimizeAccount.CapitalAssets/float64(properties.QuantProperties_.MaxHoldStockNumber-optimizeAccount.HoldStockNumber) < util.CalculateBuyStockFee(quantStockTransactRecord.StockCode, stockTransactionDataAll.OpenPrice, buyOrSellAmount) {
						if buyOrSellAmount == 100 {
							continue
						} else {
							buyOrSellAmount = buyOrSellAmount - 100
						}
					}

					// 向表optimize_stock_transact_record中插入记录
					o.db.Exec("insert into optimize_stock_transact_record(ACCOUNT_NAME, STOCK_CODE, BUY_DATE, BUY_PRICE, BUY_AMOUNT, "+
						"REGISTRATION_FEE_WHEN_BUY, COMMISSION_WHEN_BUY) "+
						"values(?, ?, to_date(?, 'yyyy-mm-dd'), ?, ?, ?, ?)",
						optimizeAccount.AccountName, quantStockTransactRecord.StockCode, transactionDate, stockTransactionDataAll.OpenPrice, buyOrSellAmount,
						util.CalculateRegistrationFee(quantStockTransactRecord.StockCode, buyOrSellAmount),
						util.CalculateCommission(stockTransactionDataAll.OpenPrice, buyOrSellAmount))

					// 更新账号的持股数量
					holdStockNumber = holdStockNumber + 1

					// 如果某个账号的持股数量已经到达最大持股数量，则跳过这个账号
					if holdStockNumber >= properties.QuantProperties_.MaxHoldStockNumber {
						io.Infoln("账号[%s]的持股数量已经到达[%d]只，不再买入股票", optimizeAccount.AccountName, holdStockNumber)
						break
					}
				}
			} else {
				io.Infoln("表quant_stock_transact_record中没有账号[%s]的持股记录，因此不再更新optimize_stock_transact_record表", optimizeAccount.AccountName)
			}
		}
	} else {
		io.Infoln("表optimize_account中没有记录")
	}
}
